I would like to run my executable right after building it by using a post-build step (add_custom_command).
So far we used a WSL environment on Windows 10, which worked. Now we switch to directly building it in the Windows cmd, which gives us an error...
CMakeLists.txt extract:
# Execute unit tests after build and write output.txt into artifact directory
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${PROJECT_NAME} ARGS -v > ${ARTIFACTS}/output.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "run ${PROJECT_NAME} in ${CMAKE_CURRENT_SOURCE_DIR}"
VERBATIM
)
Within WSL using commands 'cmake -G "Unix Makefiles" $unit_tests_root' & 'make', CMake generates file: '...\build\Pipeline\CMakeFiles\unit_tests.dir\build.make', which shows:
...
unit_tests: CMakeFiles/unit_tests.dir/link.txt
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/mnt/c/repos/project-source/tests/unit_tests/build/Pipeline/CMakeFiles --progress-num=$(CMAKE_PROGRESS_30) "Linking C executable unit_tests"
$(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/unit_tests.dir/link.txt --verbose=$(VERBOSE)
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold "run unit_tests in /mnt/c/repos/project-source/tests/unit_tests"
cd /mnt/c/repos/project-source/tests/unit_tests && /mnt/c/repos/project-source/tests/unit_tests/build/Pipeline/unit_tests -v > /mnt/c/repos/project-source/tests/unit_tests/artifacts/output.txt
# Rule to build all files generated by this target.
CMakeFiles/unit_tests.dir/build: unit_tests
...
This toolchain is working: The unit tests are executed and output is printed to output.txt.
Within cmd using commands 'cmake -G "MinGW Makefiles" %unit_tests_root%' & 'make', CMake generates the same file: '...\build\Pipeline\CMakeFiles\unit_tests.dir\build.make', which shows:
...
unit_tests.exe: CMakeFiles/unit_tests.dir/link.txt
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=C:\repos\project-source\tests\unit_tests\build\Pipeline\CMakeFiles --progress-num=$(CMAKE_PROGRESS_30) "Linking C executable unit_tests.exe"
$(CMAKE_COMMAND) -E cmake_link_script CMakeFiles\unit_tests.dir\link.txt --verbose=$(VERBOSE)
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold "run unit_tests in C:/repos/project-source/tests/unit_tests"
cd /d C:\repos\project-source\tests\unit_tests && C:\repos\project-source\tests\unit_tests\build\Pipeline\unit_tests.exe -v > C:/repos/project-source/tests/unit_tests/artifacts/output.txt
# Rule to build all files generated by this target.
CMakeFiles/unit_tests.dir/build: unit_tests.exe
...
Error message in console: (line 555 corresponds to 'cd /d C:\repos\project-source\tests\unit_tests && ...'
...
[100%] Linking C executable unit_tests.exe
run unit_tests in C:/repos/project-source/tests/unit_tests
make[2]: *** [CMakeFiles\unit_tests.dir\build.make:555: unit_tests.exe] Error 13
make[2]: *** Deleting file 'unit_tests.exe'
make[1]: *** [CMakeFiles\Makefile2:94: CMakeFiles/unit_tests.dir/all] Error 2
make: *** [Makefile:102: all] Error 2
...
What's the problem with line 555?
When I comment out the 'add_custom_command(...)' within CMakeLists.txt, the unit_tests.exe builds successfully and I can execute it manually with:
C:\repos\project-source\tests\unit_tests>.\build\Pipeline\unit_tests.exe -v > .\artifacts\output.txt
Somehow the output is not the same as the output I get when build and executed within WSL, but at least it can be executed...
Edit 1, Additional Information: I am calling these commands (cmake, make) within a python script via subprocess.run(): I have the assumption, that this locks the files - still evaluating this...
Edit 2 / Solution, I found the problem: The error actually is returned by the unit_tests.exe itself as it has 13 errors (I missed the fact, that unity exits with the amount for errors). That's why make exits with errors and deletes the executable. Now I prefer calling the executable explicitly in my python script, where I also call the cmake and make commands. #Tsyvarev, sorry for the inconvenience and thanks for your contribution. ;-)
Related
Basically, before linking is performed, I would like to convert a GCC linker script template file into a final linker script, as discussed in Can I use Preprocessor Directives in .ld file - and I'd like that step to be performed by Cmake.
I guess my problem is similar to the discussion in add_custom_command is not generating a target ; but I still cannot see how to solve it. Here is a minimal example, where I'm faking with an empty .ld linker script template file; first, let's create the files using bash:
mkdir /tmp/cmake_test && cd /tmp/cmake_test
touch my_linkerscript_template.ld
cat > main.c <<'EOF'
#include <stdio.h>
const char greeting[] = "hello world";
int main() {
printf("%s!\n", greeting);
return 0;
}
EOF
cat > CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.13)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
project(foobar C)
message("PROJECT_NAME is '${PROJECT_NAME}'")
add_executable(${PROJECT_NAME}
main.c
)
add_compile_options(-Wall
)
target_link_options(${PROJECT_NAME} PRIVATE
"LINKER:--script=${CMAKE_SOURCE_DIR}/my_linkerscript.ld"
)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/my_linkerscript.ld
DEPENDS ${CMAKE_SOURCE_DIR}/my_linkerscript_template.ld
COMMAND bash ARGS -c "gcc -E -x c -CC -I/usr/include my_linkerscript_template.ld | grep -v '^#' > my_linkerscript.ld"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "build my_linkerscript_template.ld into my_linkerscript.ld (${CMAKE_CURRENT_SOURCE_DIR})"
VERBATIM
)
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_DEPENDS "${CMAKE_SOURCE_DIR}/my_linkerscript.ld")
EOF
Note that my_linkerscript.ld is not created above; as I'd intend to put my_linkerscript_template.ld in git, and then have the final my_linkerscript.ld generated on demand.
If in this case, I do:
mkdir /tmp/cmake_test/build && cd /tmp/cmake_test/build
cmake ../ -DCMAKE_BUILD_TYPE=Debug
make
I get:
$ make
make[2]: *** No rule to make target 'D:/msys64/tmp/cmake_test/my_linkerscript.ld', needed by 'foobar.exe'. Stop.
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/foobar.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
$ grep -r linkerscript .
./CMakeFiles/foobar.dir/build.make:foobar.exe: D:/msys64/tmp/cmake_test/my_linkerscript.ld
./CMakeFiles/foobar.dir/build.make: /D/msys64/mingw64/bin/cc.exe -g -Wl,--script=D:/msys64/tmp/cmake_test/my_linkerscript.ld -Wl,--whole-archive CMakeFiles/foobar.dir/objects.a -Wl,--no-whole-archive -o foobar.exe -Wl,--out-implib,libfoobar.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
So, I did get a dependency on my_linkerscript.ld; and it did get added to linker options - but there is no build step generated by the add_custom_command.
How can I have generate the proper dependencies, so that when my_linkerscript.ld is needed for linking but it does not exist, then commands (that are given in add_custom_command above) are run, to generate this file from the template?
Output of add_custom_command needs to be "consumed" by some target, otherwise the custom command has no effect.
The property LINK_DEPENDS does NOT provide a consumer, so you need to create consumer target by yourself:
# ... in addition to your code
# Create a consumer target for the linker script.
# So previous `add_custom_command` will have an effect.
add_custom_target(my_linkerscript
DEPENDS ${CMAKE_SOURCE_DIR}/my_linkerscript.ld)
# Make executable to depend on that target.
# So, the check whether to relink the executable will be performed
# after possible rebuilding the linker script.
add_dependencies(${PROJECT_NAME} my_linkerscript)
I am following the book "Learn C the Hard Way" and I have reached the section where you compile the code using makefiles. I keep getting errors that the file was not found when running make clean.
Here is the error followed by the make file and the directory
C:\Users\Me\Desktop\C Code\HARD WAY\Dust off that compiler>make clean
rm -f main.c
process_begin: CreateProcess(NULL, rm -f main.c, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [makefile:7: clean] Error 2
EXECUTABLE=main.exe
CC="C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin\gcc.exe"
CFLAGS=-Wall -g
clean:
rm -f main
directories
EDIT: I removed the .c from the "rm -f main" as it seems to be a small error but has made no difference to the end result
EDIT 2: I worked out that the make file is issuing linux commands which is why it wasn't working, replacing rm with del fixes the issue
I worked out that the make file is issuing linux commands which is why it wasn't working, replacing rm with del and removing -f fixes the issue
I'm trying to cross compile OpenSSL for PowerPC with the FIPS module. My build host's architecture is not PowerPC. I was able to cross compile the FIPS module just fine. However, when I run make on openssl, during the linking phase, it tries to execute certain binaries to run tests. The issue is that those binaries are produced for the target architecture and, as a result, I get the error "cannot execute binary file". Is there a way to produce executables of these tests on the host architecture rather than the target architecture? Should I be handling this process differently? Here are the following commands I used to build openssl. I replaced certain directories with DIR_HIDDEN.
export FIPS_DIRECTORY="$PWD/../../openssl-fips/tgt/linux-ppc603e/"
export cross="DIR_HIDDEN/powerpc-linux-gnu-"
make clean || exit 1
make dclean || exit 1
./Configure --prefix=$PWD/../tgt/linux-ppc603e linux-ppc fips --with-fipsdir=${FIPS_DIRECTORY}
make depend || exit 1
make CC="$FIPS_DIRECTORY/bin/fipsld" RANLIB="${cross}ranlib" AR="${cross}ar r" LD="$FIPS_DIRECTORY/bin/fipsld" FIPSLD_CC="${cross}gcc" HOSTCC="/usr/bin/gcc" || exit 1
make install || exit 1
I get the following error during the make command:
shlib_target=; if [ -n "" ]; then \
shlib_target="linux-shared"; \
elif [ -n "libcrypto" ]; then \
FIPSLD_CC="/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld"; CC=/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld; export CC FIPSLD_CC; \
fi; \
LIBRARIES="-L.. -lssl -L.. -lcrypto" ; \
make -f ../Makefile.shared -e \
APPNAME=openssl OBJECTS="openssl.o verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o ca.o pkcs7.o crl2p7.o crl.o rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o s_time.o apps.o s_cb.o s_socket.o app_rand.o version.o sess_id.o ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o" \
LIBDEPS=" $LIBRARIES -ldl" \
link_app.${shlib_target}
make[2]: Entering directory `/DIR_HIDDEN/openssl/openssl-1.0.1i/apps'
( :; LIBDEPS="${LIBDEPS:--L.. -lssl -L.. -lcrypto -ldl}"; LDCMD="${LDCMD:-/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld}"; LDFLAGS="${LDFLAGS:--DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DB_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_BN_ASM_MONT -I/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//include -DSHA1_ASM -DSHA256_ASM -DAES_ASM}"; LIBPATH=`for x in $LIBDEPS; do echo $x; done | sed -e 's/^ *-L//;t' -e d | uniq`; LIBPATH=`echo $LIBPATH | sed -e 's/ /:/g'`; LD_LIBRARY_PATH=$LIBPATH:$LD_LIBRARY_PATH ${LDCMD} ${LDFLAGS} -o ${APPNAME:=openssl} openssl.o verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o ca.o pkcs7.o crl2p7.o crl.o rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o s_time.o apps.o s_cb.o s_socket.o app_rand.o version.o sess_id.o ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o ${LIBDEPS} )
/DIR_HIDDEN/openssl/openssl-1.0.1i/../../openssl-fips/tgt/linux-ppc603e//bin/fipsld: line 185: ./openssl: cannot execute binary file
make[2]: *** [link_app.] Error 126
When invoking the make command again and again, I get the same error but for all the applications located in the /test directory of the openssl tarball. Examples include bntest, ectest, and ecdhtest.
I received a similar error when I was cross compiling the FIPS module, but I was able to resolve that by including the host compiler in the HOSTCC variable. A similar trick did not work for the openssl compilation.
Any guidance would be appreciated. Thanks!
I was able to modify the make command to get the process to complete. I was missing the FIPS_SIG environment variable, which points to the incore script. The make command is now:
make FIPS_SIG=$PWD/`find ../../openssl-fips/ -iname incore` CC="$FIPS_DIRECTORY/bin/fipsld" RANLIB="${cross}ranlib" AR="${cross}ar r" LD="$FIPS_DIRECTORY/bin/fipsld" FIPSLD_CC="${cross}gcc"
I still see prints to console that indicate that openssl cannot be executed, but these are warnings and don't halt the makefile. Not really sure why or how this fixed the problem, but I'll take it.
I'm a complete beginner in using Cmake to compile my own C code and I'm running Mac OS X Mavericks.
My problem is as follow. For my intro to Cmake, created a folder containing the following folders
bin/
build/
src/
fonctions.h
fonctions.c
main.c
Here my CMakeLists.txt file:
project(Addition)
add_executable(
bin/addition
src/main.c
src/fonctions.h
src/fonctions.c
)
When I run:
$ cmake . -G "Unix Makefiles"
and then make from my root folder, no problem.
But when I run:
$ cmake .. -G "Unix Makefiles"
and then make from my /build folder I got this error message:
Linking C executable bin/addition
ld: can't open output file for writing: bin/addition, errno=2 for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/addition] Error 1
make[1]: *** [CMakeFiles/bin/addition.dir/all] Error 2
make: *** [all] Error 2
Anyone knows why?
Remove bin/ from your add_executable and use CMAKE_RUNTIME_OUTPUT_DIRECTORY to change your build location
add_executable(
addition
src/main.c
src/fonctions.h
src/fonctions.c
)
I installed netbeans to write code in C. But there is problem using Mingw compilers. It works just fine, till i try to run the project.
First it was unable to find cc1.exe while trying to run it. When i found it and manually copied into the same folder there is just another error.
"C:/bin/make.exe" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
C:\bin\make.exe[1]: Entering directory `D:/1/2/Skola/IZP/programovani/projekt4netbeans/CppApplication_6'
"C:/bin/make.exe" -f nbproject/Makefile-Debug.mk dist/Debug/MinGW_1-Windows/cppapplication_6.exe
C:\bin\make.exe[2]: Entering directory `D:/1/2/Skola/IZP/programovani/projekt4netbeans/CppApplication_6'
mkdir -p build/Debug/MinGW_1-Windows
rm -f build/Debug/MinGW_1-Windows/main.o.d
gcc.exe -c -g -MMD -MP -MF build/Debug/MinGW_1-Windows/main.o.d -o build/Debug/MinGW_1-Windows/main.o main.c
cc1: error: command line option '-lang-c' is valid for the driver but not for C
C:\bin\make.exe[2]: *** [build/Debug/MinGW_1-Windows/main.o] Error 1
C:\bin\make.exe[2]: Leaving directory `D:/1/2/Skola/IZP/programovani/projekt4netbeans/CppApplication_6'
C:\bin\make.exe[1]: *** [.build-conf] Error 2
C:\bin\make.exe[1]: Leaving directory `D:/1/2/Skola/IZP/programovani/projekt4netbeans/CppApplication_6'
C:\bin\make.exe: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 2s)
if someone could help me with that.. thanks :)
Make shure you have current versions of Netbeans and MinGw and that you have a correct installation (Configuring the NetBeans IDE for C/C++/Fortran).
On mingw you should not use make from mingw/bin, but the one from msys (<mingw>/msys/1.0/bin/make.exe)