• Activity
  • Votes
  • Comments
  • New
  • All activity
  • Showing only topics in ~comp with the tag "cplusplus". Back to normal view / Search all groups
    1. Cmake strategies or alternatives for building (different) code for different platforms

      Okay, so this is getting really long, I'll put the ask up front: I have a strategy, I think it is reasonable. Now is a point where I can easily change things, and it won't be so easily later. So...

      Okay, so this is getting really long, I'll put the ask up front: I have a strategy, I think it is reasonable. Now is a point where I can easily change things, and it won't be so easily later. So I'm looking to see if anyone has trod this road before and can recommend any of:

      1. a different build system that will be easier to manage for this use case
      2. a different strategy for using cmake that will be easier to manage
      3. any gotchas I should be aware of, even if you don't have better solutions.

      Background

      I have a project I'm working on where the ultimate deliverable will be a hardware device with 3-4 different microcontrollers coordinating with each other and interacting with a PC-ish platform. This is a clean rewrite of a C++ codebase. Due to the microcontroller (and some of the PC APIs) being C++, the language of choice for most of it is likely to remain C/C++.

      I'm succeeded in setting up a build system for embedded code. The old code was arduino, so it relies a lot on those libraries, but I've managed to set up enough custom cmake to get off of the ardunio tools altogether, even if I am borrowing their libraries and some of the "smarts" built into the system about setting build flags, etc. So far, I have a dockerized toolchain (cmake + make + gcc-arm-none-eabi) that can successfully build ARM binaries for the target platform.

      The thing that I'm up against now is that I'd like to have a robust off-target unit testing infrastructure. My ideal case is that everything in the embedded system will be broken down into libraries that have clear interfaces, then to use unit tests with mocks to get high coverage of test cases. I'll still need some HIL tests, but because those are harder to set up and run, I want to use those for integration and validation.

      In terms of OSes available, we're mostly working on Windows systems using WSL for linux. I'd like things to be as linux-based as possible to support CI on github, etc.

      Goals and Cmake limitations

      I started out using cmake because I hate it least of the tools I've used, and I am at least pretty far up the learning curve with it. But a limitation I'm hitting is that you can't do a mixed compile with two different toolchains in one build. The reasons why cmake has this limitation seem reasonable to me, even if it is annoying. You can easily change the toolchain that your code is built with, but that seems to be largely targeted at cross-compiling the same binaries for different systems. What I want to do is:

      • build my code libraries with embedded settings for linking to the embedded binaries and build those embedded binaries (the end product)
      • build my code libraries with linux-ish tools and link them against unit tests to have a nice CI test process
      • (eventually) also be able to build windows binaries for the PC components -- when I get to that point, I'd like to get away from the MSVC compilers, but will use them if I have to

      Current strategy

      My current plan is to configure a library build like this (pseudocode):

      add_library(mylib sources)
      if (BUILD_TYPE STREQUAL BUILD_TYPE_EMBEDDED)
      <embedded config>
      elseif (BUILD_TYPE STREQUAL BUILD_TYPE_LINUX)
      <linux config, if any>
      endif()
      
      #unit tests are built for each library
      if (BUILD_TYPE STREQUAL BUILD_TYPE_LINUX)
      add_executable(mylib_test sources test_sources)
      target_link_libraries(mylib gtest etc.)
      endif()
      

      For the rollup binaries, I make the whole target conditional

      if (BUILD_TYPE STREQUAL BUILD_TYPE_EMBEDDED)
      add_executable(myembedap sources)
      target_link_libraries(mylib)
      endif()
      

      Then the build script (outside cmake) is something like

      cd build/embedded
      cmake <path to src> <set embedded toolchain> -DBUILD_TYPE=embedded
      make
      cd ../../build/linux
      cmake <path to src> -DBUILD_TYPE=linux
      make
      

      Things I like about this strategy:

      • It's relatively simple to do all the builds or just one of the builds (that control would go in the shell script)
      • I have one source tree for the whole build
      • It lets configuration be near code
      • It lets tests be near code.
      • I think it's extensible to cover the PC component builds in the future

      Things that worry me:

      • It feels like a hack
      • Support for off-target tests feels like it should be solved problem and I'm worried I'm missing something

      Thanks for reading. If you made it this far, you have my gratitude. Here's a video with funny out of office messages that I enjoyed.

      6 votes
    2. Ladybird chooses Swift as its successor language to C++

      I've copied the full tweet below (it's from August, I missed this news somehow): We've been evaluating a number of C++ successor languages for @ladybirdbrowser , and the one best suited to our...

      I've copied the full tweet below (it's from August, I missed this news somehow):

      We've been evaluating a number of C++ successor languages for @ladybirdbrowser , and the one best suited to our needs appears to be @SwiftLang πŸͺΆ

      Over the last few months, I've asked a bunch of folks to pick some little part of our project and try rewriting it in the different languages we were evaluating. The feedback was very clear: everyone preferred Swift!

      Why do we like Swift?

      First off, Swift has both memory & data race safety (as of v6). It's also a modern language with solid ergonomics.

      Something that matters to us a lot is OO. Web specs & browser internals tend to be highly object-oriented, and life is easier when you can model specs closely in your code. Swift has first-class OO support, in many ways even nicer than C++.

      The Swift team is also investing heavily in C++ interop, which means there's a real path to incremental adoption, not just gigantic rewrites.

      Strong ties to Apple?

      Swift has historically been strongly tied to Apple and their platforms, but in the last year, there's been a push for "swiftlang" to become more independent. (It's now in a separate GitHub org, no longer in "apple", for example).

      Support for non-Apple platforms is also improving, as is the support for other, LSP-based development environments.

      What happens next?

      We aren't able to start using it just yet, as the current release of Swift ships with a version of Clang that's too old to grok our existing C++ codebase. But when Swift 6 comes out of beta this fall, we will begin using it!

      No language is perfect, and there are a lot of things here that we don't know yet. I'm not aware of anyone doing browser engine stuff in Swift before, so we'll probably end up with feedback for the Swift team as well.

      I'm super excited about this! We must steer Ladybird towards memory safety, and the first step is selecting a successor language that we can begin adopting very soon. πŸ€“πŸž


      Nitter link:

      https://nitter.poast.org/awesomekling/status/1822236888188498031

      Original post:

      https://x.com/awesomekling/status/1822236888188498031


      Some of Kling's replies in that thread are also pretty interesting:

      My general thoughts on Rust:
      - Excellent for short-lived programs that transform input A to output B
      - Clunky for long-lived programs that maintain large complex object graphs
      - Really impressive ecosystem
      - Toxic community

      In the end it came down to Swift vs Rust, and Swift is strictly better in OO support and C++ interop.


      The September monthly report for Ladybird released the day after I posted this. It provides basically the same information:

      This Month in Ladybird September 2024

      The section about Swift:

      Successor language search progress

      Over the past year, our core contributors have been exploring potential safe languages to complement or succeed C++. We evaluated several options, including Rust, Swift, Fil-C, and others. While some languages offered compelling features, many fell short in either C++ interoperability or providing the level of memory safety we needed.

      After extensive testing and discussion, Swift emerged as the top choice among our core developers, thanks to the new Swift 6 interoperability features and its growing cross-platform support. As a result, we’ve decided to adopt Swift as our C++ successor language.

      That said, this will be an incremental shift. The existing C++ codebase is deeply embedded in the project, and a complete rewrite would be impractical. Instead, we’ll be gradually introducing new components in Swift, carefully integrating them with our existing C++ code over time. Look forward to a dedicated blog post on the topic soon.

      32 votes
    3. Help with finding out more about an obsure c++ graphics library

      I recently started classes again a little over a week ago. One of the classes I am taking is Computer science 2. One of the things it includes is openGL based graphics programming. They have us...

      I recently started classes again a little over a week ago. One of the classes I am taking is Computer science 2. One of the things it includes is openGL based graphics programming. They have us using glut, which is not bad in it self. However what they do is provide us a wrapper library for glut. In the form of a header named "graph1.h" and a precompiled library. Which goes by various names, such as "graphLib1.lib", "graphLib2010.lib", "graphLib2022.lib", "graphicLib2015.lib", etc. It's provided in the form of Windows flavored x86, Macos flavored x86_64 and arm. However, no forms for Linux. While I have been using Windows and VS Studio for classes so far, I strongly prefer my current Linux based tool chain. (text editor, build system, debugger). I have tried cross compiling with mingw-w64, but it fails when I try to link it. I would very much like to use it natively. To do this I would need either the library or the sources to compile it myself. That is what I would really like to find.

      Here is more about the library it self. It is based off of BMPLoader, a small library for loading bitmaps as openGL textures. It also inherits its license from BMPLoader too, because it is a derivative of BMPLoader. (GPLv2; and has been distributed). When you unpack the library there are 3 object files, BMPLoader.o, loadPNG.o, and example2.o. (.o/.obj) I have found traces of it online, however they all link back to my University, University of Central Arkansas. I have also found evidence of it being used at GSU too, but it is from one of the professors that is now here at UCA. (They even provided a pdf on using it, I hashed them and they were the same). Here is a copy of the header graph1.h.

      graph1.h
      /*BMPLoader - loads Microsoft .bmp format
          Copyright (C) 2006  Chris Backhouse
      
          This program is free software; you can redistribute it and/or modify
          it under the terms of the GNU General Public License as published by
          the Free Software Foundation; either version 2 of the License, or
          (at your option) any later version.
      
          This program is distributed in the hope that it will be useful,
          but WITHOUT ANY WARRANTY; without even the implied warranty of
          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
          GNU General Public License for more details.
      
          You should have received a copy of the GNU General Public License along
          with this program; if not, write to the Free Software Foundation, Inc.,
          51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      
      
        cjbackhouse@hotmail.com 		www.backhouse.tk
        
        I would appreciate it if anyone using this in something cool would tell me
        so I can see where it ends up.
      
        Takes a filename, returns an array of RGB pixel data
        Loads:
        24bit bitmaps
        256 colour bitmaps
        16 colour bitmaps
        2 colour bitmaps  (Thanks to Charles Rabier)
      
        This code is designed for use in openGL programs, so bitmaps not correctly padded will not
        load properly, I believe this only applies to: 
        256cols if width is not a multiple of 4
        16cols if width is not a multiple of 8
        2cols if width is not a multiple of 32
      
        Sample code:
      
      	BMPClass bmp;
      	BMPLoad(fname,bmp);
      	glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes);
      */
      #include <windows.h>
      #include <gl/glut.h>
      #include <iostream>
      #include <cstring>
      #include <string>
      #define endg "_endg_"
      
      
      #ifndef BMPLOADER_H
      #define BMPLOADER_H
      
      #include <iostream>
      #include <cstring>
      
      using namespace std;
      
      typedef unsigned char BYTE;
      
      class BMPClass
      {
      public:
      	BMPClass();
      	~BMPClass();
      	BYTE& pixel(int x,int y,int c);
      	void allocateMem();
      	int width,height;
      	BYTE* bytes;			//OpenGL formatted pixels
      };
      
      #define BMPError char
      #define BMPNOTABITMAP 'b'	//Possible error flags
      #define BMPNOOPEN 'o'
      #define BMPFILEERROR 'f'
      #define BMPBADINT 'i'
      #define BMPNOERROR '\0'
      #define BMPUNKNOWNFORMAT 'u'
      
      //Loads the bmp in fname, and puts the data in bmp
      BMPError BMPLoad(string fname,BMPClass& bmp);
      
      //Translates my error codes into English	
      std::string TranslateBMPError(BMPError err);	
      
      //Load and select in OpenGL
      BMPError BMPLoadGL(string fname);
      
      struct Precision
      {
        int precision;
        bool precisionFlag;
      };
      
      struct GraphColor
      {
        int r;
        int g;
        int b;
      };
      
      class Gout
      {
        private:
          int x;
          int y;
          int r;
          int g;
          int b;
          int precision;
          bool precisionFlag;
      
      
        public:
          Gout() { r= 0; g=255; b= 0; precisionFlag = false; };
          void setX(int x) { this->x = x;}
          void setY(int y) { this->y = y;}
          int getX() { return x;}
          int getY() { return y;}
          void setR(int r) {this->r = r;}
          void setG(int g) {this->g = g;}
          void setB(int b) {this->b = b;}
          int getR() {return r;}
          int getG() { return g;}
          int getB() {return b;}
          void setPrecisionFlag(bool flag) { precisionFlag = flag;}
          bool getPrecisionFlag() {return precisionFlag;}
          void setPrecision(int precision) {this->precision = precision;}
          int  getPrecision() {return precision;}
          friend Gout& operator<<(Gout& g, int int_val);
          friend Gout& operator<<(Gout& g, double int_val);
          friend Gout& operator<<(Gout& g, char* char_val);
          friend Gout& operator<<(Gout& g, string string_val);
         
      };
      
      extern Gout gout;
      
      struct Point
      {
        int x;
        int y;
      };
      
      
      
      struct GraphObject
      {
        char* str;
        int id;
        int no_points;
        Point* points;
        double* colors;
        int radius;
        int no_objects;
        BMPClass* bmp;
        int remove;
        int width;
        int height;
        int del;
        BYTE* bytes; //PNG BYTES
      };
      
      void reshape(int w, int h);
      void display(void);
      void init(char* title);
      int drawPoint(int x, int y);
      int drawCircle(int radius, int x, int y);
      void drawMyCircle( int Radius, int numPoints, int x, int y );
      int drawLine(int x1, int y1, int x2, int y2, int width);
      int drawRect(int x1, int y1, int width, int height);
      void displayGraphics();
      int displayBMP(char* fn,int x, int y);
      int displayBMP(string fn, int x, int y);
      int displayPNG(string fn, int x, int y);
      int displayPNG(char* fn, int x, int y);
      int displayText(char* str, int x, int y, int r, int g, int b);
      void clearGraphics();
      void setColor(int obj_no, int r, int g, int b);
      GraphColor setColor(int r, int g, int b);
      void timerColor(int value);
      void moveObject(int obj_no, int x, int y);
      void processSpecialKeys(int key, int x, int y);
      DWORD WINAPI display1(LPVOID lpParam);
      void processMouse(int button, int state, int x, int y);
      void removeObject(int id);
      void clearText();
      void GRAPH_SS();
      bool up();
      bool down();
      bool left();
      bool right();
      bool leftMouse(int&x, int&y);
      bool rightMouse(int&x, int&y);
      bool middleMouse(int&x, int&y);
      Gout& operator<<(Gout& g, int int_val);
      Gout& operator<<(Gout& g, double int_val);
      Gout& operator<<(Gout& g, char* char_val);
      Gout& operator<<(Gout& g, char char_val);
      Gout& operator<<(Gout& g, Gout&(*pt2Func)(int x, int y));
      Gout& operator<<(Gout& g, Gout&(*pt2Func)(int r, int g, int b));
      Gout& operator<<(Gout& g, Point a);
      Gout& operator<<(Gout& g, GraphColor gc);
      Gout& operator<<(Gout& g, Precision p);
      Gout& operator<<(Gout& g, Gout&(*pt2Func)(int precision));
      Precision setPrecision(int precision);
      Point setPos(int x, int y);
      void getPos(int obj_no, Point points[], int& no_points);
      bool mouseDragged(int& x, int& y);
      void processMouseDragged(int x, int y);
      void replaceObject(int orig_obj, int new_obj);
      void closeGraphics();
      
      #endif
      

      Right now I am of the opinion that it is a in-house "hackjob". That is how it feels with the GPLed BMPLoader glued together with other graphics functions. In an attempt to not have to use new literature or new style libraries with the new ".net 2008" style ide, as they were likely transitioning out of a codewarrior environment, and before that a borland environment.

      So far, I have asked our computer science club about it. The main thing I was told was that the professor just wants us to use windows. That I can understand, but I still want to see how far I can go. I have also tried sending an email about it to the professor, but all I got sent was a link to the glut downloads. I did reply back asking about the graphlib sources too, but I haven't heard anything back yet. I don't want to push too hard, I still have a whole semester ahead of me. So now I am asking here on tildes. I understand if nothing can be found, but at least information and experiences can be collected.

      11 votes
    4. How do you structure larger projects?

      I'll be writing a relatively large piece of scientific code for the first time, and before I begin I would at least like to outline how the project will be structured so that I don't run into...

      I'll be writing a relatively large piece of scientific code for the first time, and before I begin I would at least like to outline how the project will be structured so that I don't run into headaches later on. The problem is, I don't have much experience structuring large projects. Up until now most of the code I have written as been in the form of python scripts that I string together to form an ad-hoc pipeline for analysis, or else C++ programs that are relatively self contained. My current project is much larger in scope. It will consist of four main 'modules' (I'm not sure if this is the correct term, apologies if not) each of which consist of a handful of .cpp and .h files. The schematic I have in mind for how it should look is something like:

      src
       β”œβ”€β”€Module1 (Initializer)
       β”‚         β”œ file1.cpp
       β”‚         β”œ file1.h
       β”‚         β”‚...
       β”‚         β”” Makefile
       β”œβ”€β”€β”€Module2 (solver)
       β”‚          β”œ file1.cpp
       β”‚          β”œ file1.h
       β”‚          β”‚...
       β”‚          β”” Makefile
       β”œβ”€β”€β”€Module3 (Distribute)
       β”‚          β”œ file1.cpp
       β”‚          β””Makefile 
       β”” Makefile
      

      Basically, I build each self-contained 'module', and use the object files produced there to build my main program. Is there anything I should keep in mind here, or is this basically how such a project should be structured?

      I imagine the particularly structure will be dependent on my project, but I am more interested in general principles to keep in mind.

      14 votes