Eclipse CDT - how to use an argfile for the linker for a too long command line - c

I'm using Eclipse CDT 9 Neon with GCC 6.3 on Windows 7 for a STM32 project.
I have installed the GNU ARM Plug-in and use sh.exe for long command line management (cmd.exe from windows have a limite of 8192 char) for calling make.exe (GNU Coreutils date: 04.06.2009).
I'm working on a big project.
Without build exclusion my linker command line is over 33 000 char and generate an error on the linker command line.
With builds exclusions and a reduced version of my project, I have reduce the linker command line to 15 600 char, compilation worked fine and my binary file is operational.
At first, for the full version of my project, the linker command line is bigger than 20 000 char and generate an ACCESS VIOLATION on sh.exe.
With an other version of sh.exe (from Microsemi IDE) I have no more ACCESS VIOLATION on sh.exe and be able to link more file.
But for the full version of my project I have a link error :
make (e=87): Paramètre incorrect.
This error come from a to long command line (more than 32 000 char).
Other IDE (Winidea with GCC) use an argument file that combine linker file (.ld) and the obj files list to have a very short linker command line.
How can I configure GCC in Eclipse to use an argument file for the linker ?
I found a solution, not perfect but fully operational. I have writen an bat file to generate obj listing file.
Instructions to use it are in rem.
I have writen the file "gen__link_ld.bat" :
echo off
rem ***************************************************************************
rem Generate script file for the linker to go throuth linker command line too
rem long trouble under windows (32 000 char max)
rem ***************************************************************************
rem Lunch in pre-build step is not advised, this commande is run in paralel
rem with build step that can temporarie supress obj file need to run
rem compilation a 2nd time to have a script file up to date for the linker.
rem Run in pre-build step generate trouble in debug mode.
rem
rem Use manual lunch with 2 parameters :
rem create a .bat file per build with the folowing commande :
rem gen__link_ld.bat ./project relative path and .ld file name ./project relative build path
rem in linker commande line pattern replace {INPUT}
rem by -Xlinker --script=${ProjDirPath}/${ConfigName}/___link.ld
rem and add manualy librairie after ___link.ld, in this case library include
rem throuth graphical build setting don't work, they may use {INPUT} from the
rem standard commande
rem ***************************************************************************
echo **************************************************************************
echo ***************************** *****************************
echo ***************************** WARNING *****************************
echo ***************************** *****************************
echo **************************************************************************
echo Generate script file for the linker to go throuth linker command line too
echo long trouble under windows (32 000 char max)
echo
echo List only existing obj file.
echo The best way is to use manual lunch with one .bat file per build.
echo follow information in r e m above to use it.
echo
echo Run this commande evry time that obj liste is modified.
echo WARNING this function don't delete obj file for file recently exclude
echo frome build.
echo To secure the compilation need a clean to suppress all obj, run a first
echo build witch compile all file without error (with only linker error) to
echo generate an obj file listing up to date and run a second buid for a
echo successful linker step. When the OJB file listing is up to date, only
echo eclipse build commande is needed
echo **************************************************************************
echo Linker file use : %1
echo Build path use : %2
echo **************************************************************************
setlocal ENABLEDELAYEDEXPANSION
set destination=%2
set destination=%destination:/=\%
rem *** Generate obj file listing ***
echo INPUT(>%destination%\___link.ld
dir %destination%\*.o /s /b >>%destination%\___link.ld
echo )>>%destination%\___link.ld
rem *** Concatenat obj file listing with ld file from parameter 1 ***
set str=%1
set str=%str:/=\%
type %str%>>%destination%\___link.ld
echo *** OBJ file listing up to date
echo **************************************************************************
pause
Thanks

Here's a simple workaround I've found for the issue (using a small python script), on the same line of thought of separating the object listing in another file - note that these kind of files are called response files in the GNU world: https://gcc.gnu.org/wiki/Response_Files and they separate the entire command-line rather than only the object files and libraries.
Assuming you're using the GNU Make builder+GNU linker:
You'll need to create a python script and place it somewhere in your project, I'll assume the path to the script is build/link_with_rsp_file.py. Place in it the contents below.
Go to project properties -> C/C++ Build -> Settings. Make sure the appropriate build configuration is selected. You should find the toolchain settings there.
Select the linker item. Depending on your build configuration, you should have a Command/Command line pattern pair such as g++/${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}. We'll assume it looks just like this, adjust accordingly.
Change the command-line pattern to #$(file >linkcl.rsp,${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS})python ../build/link_with_rsp_file.py linkcl.rsp ${COMMAND}. This effectively tells GNU make to take all the linker arguments, put them in the response file linkcl.rsp (using the $(file) function) and then run the linker (${COMMAND}) using the generated response file instead.
Python script:
import sys, subprocess
def cmd_exec(full_cmd):
print(full_cmd)
sys.stdout.flush(); sys.stderr.flush()
p = subprocess.Popen(full_cmd.split(' '))
p.communicate()
return p.returncode == 0
rsp_file, cmd = sys.argv[1], sys.argv[2:]
cmd = ' '.join(cmd)
# First replace all '\' with '/' in the response file (bash doesn't deal well with '\')
with open(rsp_file, "r") as f: linkcl = f.read()
linkcl = linkcl.replace('\\', '/')
with open(rsp_file, "w") as f: f.write(linkcl)
# Call the linker
cmd_exec("{cmd} #{rsp_file}".format(cmd=cmd, rsp_file=rsp_file))

I've improved the way in https://stackoverflow.com/a/61644057/5789722 :
Go to project properties -> C/C++ Build, and ensure Builder type is External builder and enable Generate Makefiles automatically
Go to project properties -> C/C++ Build -> Settings, select Tool Settings -> a linker like Cygwin C++ Linker
fill Command line pattern with:
#$(file >linkcl.rsp,$(subst \,/,${FLAGS}) ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}) ${COMMAND} #linkcl.rsp
here I use subst to replace \ with /, then link_with_rsp_file.py is not needed any more

Related

What is the xc16 command to obtain disassembly (listing.disasm) file?

I want to obtain disassembly (listing.disasm) file for my project. My current compilation commands produces .elf, .map and .hex files.
How do I (Or what commands) produce a single listing.disasm?
Note: I have multiple C files, but I need a single disassembly file.
I know that there is a option in MPLAB X IDE to create listing.disasm while building. But I'm building using batch file.
Compiler: XC16
Processor Family: PIC24F
If you are using MPLABX, go to Project Properties -> Building, check "Execute this line after build", then add this:
${MP_CC_DIR}\xc16-objdump -S ${ImageDir}\${PROJECTNAME}.${IMAGE_TYPE}.elf > list.lst
Know you should find the list file in your x-folder.
If you work with a batch file, maybe try this:
if "%1" == "cof" goto coff_file_format
:elf_file_format
#echo dump for ELF/DWARF
xc16-objdump -omf=elf -S %2\%3.%4.elf > %2\%3.%4.lst
goto end
:coff_file_format
#echo dump for COFF
xc16-objdump -omf=coff -S %2\%3.%4.cof > %2\%3.%4.lst
:end

How to create a batch script which takes list of files as argument and passes to an exe

I am trying to create a batch file which runs an exe with arguments.
The exe needs an input file as argument.
Instead of specifying file name as argument, I would like to consider all files residing in that folder as input to exe.
Below is the syntax I have used in the batch script and executed it. Upon running below code batch script stopping suddenly.
However, when I specify the file name and run from command prompt the execution is successful.
Example:
Example.exe -i c:\Test\*.wav -o c:\result
I have looked at few of the examples in Google and found that I can use *.fileextension to refer that particular files in the folder.
I am thinking if there is a better approach to achieve this.
I am assuming you will run the same command and switch for multiple wav files.
#echo off
for %%i in (*.wav) do (
example.exe -i %%i -o c:\result
)

Automating the creation of new file in windows folder

I am trying to write a batch script which will check if there are any file with , say for example, .dll extension and if file exits then it should create new file with same name but with .txt extension.
so say I have test_12345.dll file present in folder then my script should see if this exits and create an empty file as test_12345.txt ( basically exact same name with .dll file but with different extension)
Can some expert help me to create this with batch script.
Regards
Sushant
This is the bash script. :) You could try this in bash environment.
#!/bin/bash
dirname=$1
ext=$2
[ $# -eq 0 ] && { echo "Usage: $0 <path> <ext>" ex: $0 /tmp/ dll ; exit 1; }
find $dirname -type f -name "*.${ext}" | while read fname
do
name=$(dirname $fname)/$(basename $fname .${ext})
txtFile=$name.txt
if [ ! -e "$txtFile" ] ; then
touch "$txtFile"
fi
done
This is a windows bat script doing what you need.
Scans all DLLs in the current directory, then changes extension to .txt and creates an (almost) empty file. Full batch native, no external tools used.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for %%b in (*.dll) do (
set v=%%b
set u=!v:.dll=.txt!
echo. >!u!
)
Supposing you are looking fo a batch-file solution, this is what you want:
for %%F in ("\path\to\folder\*.dll") do (
> "%%~dpnF.txt" break
)
The for loop enumerates all .dll files in the given location \path\to\folder\ (remove that part if you want to process the current working directory). %%~dpnF expands to drive, path and base name (without extension .dll) of the currently iterated item. The break command does nothing in modern Windows systems (it is just there for backwards compatibility with MS-DOS) and produces no output, hence I use it to create empty .txt files. echo. returns a line-break (so the files are not empty); furthermore the . syntax might even cause unexpected behaviour under some circumstances (the syntax echo( looks odd but it is secure).

7-zip command line - Incorrect wildcard type marker

I'm using 7-zip 15.14 64-bit on Windows 10. I have a batch file that compiles a game I'm working on, only problem is I get an error about an "Incorrect wildcard type marker". Here is the line of code taken right from the batch file.
"%ProgramFiles%\7-Zip\7z.exe" a "%expt%\Game_Win.exe" "%expt%\Win\*" -x!*.m4a -sfx -mx9 -y
Note that I do have symbolic links in the directory I'm trying to compress.
It sounds like you have enabledelayedexpansion turned on.
With this mode, ! symbols have special meaning, and to make matters more interesting, there are two parse passes on each line, meaning you'll need to double escape them to have the symbol pass through to the target application:
echo "%ProgramFiles%\7-Zip\7z.exe" a "%expt%\Game_Win.exe" "%expt%\Win\*" -x^^!*.m4a -sfx -mx9 -y

Deciphering "Make EXE from BAT" Script written by Jason Faulker

I came across a way to convert my .bat with dependencies on tool to an .exe file. However when I try using the script and run the .exe created, I always getting an error. Seems I modified the script incorrectly.
Anyone can help, please?
Here's the code with my modifications:
#ECHO OFF
ECHO Make EXE From BAT
ECHO Written by: Jason Faulkner
ECHO SysadminGeek.com
ECHO.
ECHO.
REM Usage:
MakeExeFromBat BatFileToConvert -bat MyProgram.bat
REM
REM Required Parameters:
BatFileToConvert -save MyProgram
REM Source batch file to use to produce the output Exe file.
REM
REM Optional Parameters:
IncludeFile -include Tool.exe
REM Additional files to include in the Exe file.
REM You can include external tools used by the batch file so they are available on the executing machine.
SETLOCAL
REM Configuration (no quotes needed):
SET PathTo7Zip=C:\Desktop\
REM ---- Do not modify anything below this line ----
SET OutputFile="%~n1.exe"
SET SourceFiles="%TEMP%\MakeEXE_files.txt"
SET Config="%TEMP%\MakeEXE_config.txt"
SET Source7ZFile="%Temp%\MakeEXE.7z"
REM Remove existing files
IF EXIST %OutputFile% DEL %OutputFile%
REM Build source archive
ECHO "%~dpnx1" > %SourceFiles%
:AddInclude
IF {%2}=={} GOTO EndInclude
ECHO "%~dpnx2" >> %SourceFiles%
SHIFT /2
GOTO AddInclude
:EndInclude
"%PathTo7Zip%\7za.exe" a %Source7ZFile% #%SourceFiles%
REM Build config file
ECHO ;!#Install#!UTF-8! > %Config%
ECHO RunProgram="%~nx1" >> %Config%
ECHO ;!#InstallEnd#! >> %Config%
REM Build EXE
COPY /B "%PathTo7Zip%\7zsd.sfx" + %Config% + %Source7ZFile% %OutputFile%
REM Clean up
IF EXIST %SourceFiles% DEL %SourceFiles%
IF EXIST %Config% DEL %Config%
IF EXIST %Source7ZFile% DEL %Source7ZFile%
ENDLOCAL
This doesn't really convert a bat file to an exe. It just creates a selfextracting archive (exe) which contains the bat file. On execution it extracts the file to a temporary folder and runs it from there. You can even extract the bat from the exe just by using 7zip/rar/winzip or any other archiver.
If you want to convert a bat to an exe for real you should use one of the tools from the web (like this one: http://www.f2ko.de/index.php?lang=en) or concider using a simple script language like AutoIt.
If you pick the second, you can simply execute your bat code with Run("put your bat code in here") and you can compile your script to a "real" exe file.
For an alternative approach, you can basically do the same thing as described in the accepted answer (making a 7z-SFX) with WinRAR. That way, you can also do it with a GUI, and I will try to add some more useful information.
Actually, you can also use the latter approach to generate portable applications and it also works with "converting" every runnable (or openable) file into an .exe.
If you need that "portability hack", you should unpack your .exe or .msi installer with Universal Extractor. Details can be found in this Article, Step 1 to 4. Newer Versions of 7zip or WinRAR also come with comparable features.
Now you add all needed files to the archive. In the easiest case, this is just your .bat script or whatever file you want to "convert" into an .exe applivation. (Step 5 here)
Steps 6 and 7 are just some Settings for the SFX-Archive, 8 is the interesting one, as you select what you actually want to run there. Input the name of your (.bat-)file.
Step 9 lets you select where to unpack to - you do this setting manually and programmatically in the MakeExeFromBat.bat-script.
After this process you created a Portable App in SFX archiever form, enjoy
The word "converting" was put into quotation marks, because running that .exe actually works like this:
The contents of the (SFX-)EXE file are extracted from the "archive part" to a directory as the specified temp directory.
( The config file generated by the script is read. )
The file, that was previously contained in the EXE file and then extracted, is now executed in a new window.
a) This file could besides a .bat be anything - as e.g. an image, a MP3 or a video
b) or also a Python Script (of course your OS needs to know how to deal with that file.
Once finished, the temp files are removed.
You can also derive some limitations from that. If you have a .bat that needs the content of the working directory, you will have a problem. (Say, a batch that renames all files in the current dir from 1 to n.) In some cases that can be dealt with by adding all needed files to the archive too. On Windows Vista and all newer OSes, you might encounter a message box after the script is run. After selecting ‘This program installed correctly’, the message box will not be displayed in the future for this file. Because the EXE file launches in a new window, the typical way of logging output (using the > char) will not work as expected. In order to log the output, you would need to handle this natively in your source script.
All references were already linked, but once again: Big credit goes to Jason Faulkner for providing the Article and 7zip-Approach, binbert for the WinRAR-SFX Solution (which is as hinted much more versatile -> portability) and some credit to creative8 for finding the two and the article comparing them.
Actually, I was develping another solution using AutoHotkey. In my case, I just want to be able to add my .bat to the windows start menu - but the options are not limited to that.
The script itself is just a oneliner and .AHK is easily converted to .exe (I used v1.1.33.09):
run % SubStr(A_ScriptName, 1, -4) ;// run also has the option to run your file minimized or hidden, see the source 2 below
Source 2
What it does is taking its own name, removing the .ahk or .exe respectively (the last 4 characters, hence -4) and running excactly that. Usage could not be easier: you have a runme.bat, so you rename the program I provide to runme.bat.exe. Say you want the .exe to open an image.png - guess what, rename it to image.png.exe. You get the gist - that's it. It dynamically checks its name to find what to run. In my opinion, this is not much less mighty than "unpacking the .bat and then run it", but (again imho) it is much more elegant.
Use it as you wish, I should probably start a public github page or so.

Resources