On 05/02/2024 16:51, Malcolm McLean wrote:
One problem as I see is that the build system doesn't know which C
compiler is available, or which one the client wishes to use.
The client will know that, so can simply supply that information.
However it is needed in two places:
(1) The compiler used to build build.c (as it's called in the demo
below).
(2) The compiler used by build.exe to build the app.
(1) is easy, the client is just told to use their prefered compiler here:
tcc build.c
But the next step is harder: build.exe won't know what was typed in step
(1). Even if they do 'tcc -run build.c', 'tcc' does not appear as
'args[0]', it will be 'build.c' (not even build.exe).
Here is a mock-up anyway of a build system:
1) The demo app used has three C files cipher.c, hmac.c,sha2.c
2) There is a program called build.c
3) The data describing the project is in a file called here
filelist.txt, although it contains C source code.
Files (2) and (3) are shown below. It runs like this, using tcc's run
option:
c:\c>tcc -run build.c
Compiler = tcc
Invoking compiler:tcc -o cipher.exe cipher.c hmac.c sha2.c
Finished building: cipher.exe
build.c defaults to using tcc. For use with another compiler, the
process looks like this:
c:\c>gcc build.c -o build
c:\c>build gcc
Compiler = gcc
Invoking compiler:gcc -o cipher.exe cipher.c hmac.c sha2.c
Finished building: cipher.exe
It's a litle untidier. However you can always provide a makefile to shut
people up. The difference here is:
* The makefile only contains the handful of lines needed to implement
the above
* The process can be easily be done manually if needed
* The critical build info, the list of files, is inside the file
filelist.txt. While it is C, it can still be presented in a readable
manner. It can even be incorporated into the user's own programs.
The info in filelist.txt is simplistic. It also needs the locations of
any special headers, the libraries to use and and so on. This is all
info added to the final invocation.
Ideally build.c, knowing the name of the compiler, can select the right
forms of any options needed.
--------------------------------------------------------------
filelist.txt
--------------------------------------------------------------
//#define exeext = ".exe"
char* files[] = {
"cipher.c",
"hmac.c",
"sha2.c"
};
int nfiles = sizeof(files)/sizeof(files[0]);
char* projectname = "cipher";
char* exefilename = "cipher.exe";
--------------------------------------------------------------
--------------------------------------------------------------
build.c
--------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "filelist.txt"
char* compiler;
void error(char* mess, char* param){
printf("Build error: %s %s\n",mess, param);
exit(1);
}
void compileproject(void) {
int n, length, i;
char* cmdstr;
length=0;
for (i=0; i<nfiles; ++i) length+=strlen(files[i])+1;
cmdstr=malloc(length+100);
strcpy(cmdstr, compiler);
strcat(cmdstr, " ");
strcat(cmdstr, "-o ");
strcat(cmdstr, exefilename);
strcat(cmdstr, " ");
for (i=0; i<nfiles; ++i) {
strcat(cmdstr, files[i]);
strcat(cmdstr, " ");
}
printf("Invoking compiler:");
puts(cmdstr);
if (system(cmdstr)!=0)
error("Error building:", exefilename);
else
printf("Finished building: %s\n", exefilename);
}
int main(int n, char** args) {
if (n>=2)
compiler=strdup(args[1]);
else
compiler="tcc";
printf("Compiler = %s\n", compiler);
compileproject();
}
--------------------------------------------------------------