Author Topic: Problems compiling to executables on Linux  (Read 4205 times)

0 Members and 1 Guest are viewing this topic.

Offline dchr

  • Newbie
  • Posts: 1
    • View Profile
Problems compiling to executables on Linux
« on: September 09, 2018, 07:16:16 am »
Dear all,

recently, I experienced an issue that may or may not be related to another recent thread on this forum ("QB64 v1.2 on Linux and OS/X has big problems!").

I noticed this on a fresh install of QB64 (latest stable version) on the latest release of Linux Mint as well a few days ago - both the QB64 executable itself, as well as the compiled executables themselves, could not be executed by double-clicking them in the file manager (although, in my case at least, the compilation itself worked), because they were misidentified as "shared libraries" instead of executables (all permissions are set correctly). Running them from the terminal window works fine, though.

I am not entirely sure myself what the root of the issue is, but gcc, by default, compiled them as shared libraries instead of executables:

https://bugs.launchpad.net/ubuntu/+source/shared-mime-info/+bug/1639531

I have since managed to fix the problem for the QB64 executable by adding the -no-pie compiler switch to the setup script, following a suggestion in this thread:

https://stackoverflow.com/questions/45329372/ubuntu-recognizes-executable-as-shared-library-and-wont-run-it-by-clicking

But obviously this has the side effect of the executable not being position-independent any more. If the fix does indeed have something to do with setting compiler / linker switches, this might require some adjustments to the QB64 code to restore the default behaviour on certain Linux distros. Has anyone else experienced this problem?

Hello, QB64 community, by the way! Pleased to meet you.

Offline Fifi

  • Forum Regular
  • Posts: 181
    • View Profile
    • My small QB64 contribution
Re: Problems compiling to executables on Linux
« Reply #1 on: September 09, 2018, 12:37:55 pm »
Hi dchr,

I've a similar problem on many Ubuntu (14.04.5, 16.04.5, 18.04.2) and Mint (17.3, 18, 19) releases with the two last stable (20180202/85 and 20180228/86) builts as well as with the last dev built.

The amazing part of this problem is that it doesn't affect GUI apps such as Inform or vWATCH64.

However, vWATCH64 can't fire the console (e.g. my loan.bas program is rebuilt as loan.vwatch.bas and the executable
loan.vwach is created but vWACTH64 can't fire it).

So, is there a specific reason why console apps can't be fired anymore but only via the command line ?

I'll try later with previous releases of Ubuntu (12.04.5 and 14.04.1) just in case.

Question to all the community : does anyone has a QB64 for Linux built prior to 20180202/85 ?

TIA
Fifi
« Last Edit: September 09, 2018, 01:35:55 pm by Fifi »
It's better to look like an idiot for a short time while asking something obvious to an expert than pretending to be smart all your life. (C) Me.

Offline Fifi

  • Forum Regular
  • Posts: 181
    • View Profile
    • My small QB64 contribution
Re: Problems compiling to executables on Linux
« Reply #2 on: September 10, 2018, 05:15:38 am »
Another point about this problem: it doesn't occur with very small program such as a simple PRINT "Hello Word!" but only with larger codes.

However, my loan.bas sample has only 332 lines of code.

I've no explanation about the crritical size of the .bas and will investigate this further today.
It's better to look like an idiot for a short time while asking something obvious to an expert than pretending to be smart all your life. (C) Me.

Offline Fifi

  • Forum Regular
  • Posts: 181
    • View Profile
    • My small QB64 contribution
Re: Problems compiling to executables on Linux
« Reply #3 on: September 10, 2018, 04:31:52 pm »
Hi all again,

Just reinstalled Ubuntu 1.04.1 64 (Trusty) into a VM with an old QB64 release 1.0 and the problem was already there !

QB64 can create the executable but, with my loan.bas sample, can't fire it!

I also installed QB64 v1.2 but without any success to solve this problem.

Since I've been out of the QB64 scope for a while, in fact, I guess nobody ever tested QB64 on a Linux box (bare-metal or VM) with even a medium sized .bas source file doing outputs to a terminal session.

Once again, even with QB64 v1.0 on Trusty, the executable is created but can't be fired by QB64.

However, the executable can be fired via the simple command line; ./loan.

So, it's a very old problem nobody ever noticed.

Once again, below is my loan.bas code to test:

Code: QB64: [Select]
  1. '
  2. ' Program name: loan.bas
  3. '
  4. ' Program that computes for a client the montly payments, interest, principal
  5. ' and balance for a certain amount with a certain fixed interest rate and for
  6. ' a certain number of years and prints the amortization table.
  7. '
  8. ' The executable can be launched with four parameters : name of the client,
  9. ' amount, interest and term.
  10. '
  11. ' The parameters must be entered using a command line arguments in a string of
  12. ' the form: "&name=abcd&amount=xxx&rate=rr.rr&term=zz"
  13. ' where name is the client name (a string without space)
  14. ' xxx is the amount (a long)
  15. ' rr.rr is the rate (a float) - maximum 20
  16. ' and zz is the number of years (an int) - maximun 99
  17. ' e.g. loan &name=John&amount=12000&rate=2.57&term=5
  18. '
  19. ' NOTE:
  20. ' Space(s) can be included between arguments but not between the argument
  21. ' and the sign "=" nor between the sign "=" and the argument value such as:
  22. ' e.g. loan & name=John & amount=12000 & rate=2.57 & term=5
  23. '
  24. ' NOTE:
  25. ' Only the dot sign "." is allowed in float to separate the integer part from
  26. ' its decimal part (no comma sign "," anywhere in a float).
  27. '
  28. ' NOTE:
  29. ' If no parameters are set, the program ask you the values.
  30. ' If there is no value entered (just hit the Enter key), the program computes
  31. ' the default values (Client, 10000.00, 3.5% and 5 years).
  32. '
  33. '
  34. ' title of the windows when used in a console
  35. '
  36. _TITLE "Loan calculator"
  37. '
  38. ' miscelaneous variables initialisation
  39. '
  40. Arg$ = ""
  41. NbArg% = 0
  42. DIM ArrayArg$(4)
  43. lastPayment# = 1.00
  44. Year% = 1
  45. '
  46. ' Get the Arguments of the command line
  47. '
  48. LineArg$ = COMMAND$
  49. '
  50. ' force parameters if the argument line is empty.
  51. '
  52. IF LEN(LineArg$) = 0 THEN
  53.     '    LineArg$ = "& name=- & amount=10000.00 & rate=3.5 & term=1"
  54.     PRINT "Please enter your name (any name, may be empty but no space):     ";
  55.     INPUT yourname$
  56.     PRINT "Amount to borrow (long, decimal characters) e.g. 1000000:         ";
  57.     INPUT amount$
  58.     PRINT "Rate of the loan (float, decimal characters with .) e.g. 1.65 :   ";
  59.     INPUT rate$
  60.     PRINT "Number of year of the loan (integer, decimal characters) e.g. 12: ";
  61.     INPUT term$
  62.     LineArg$ = "& name=" + yourname$ + " & amount=" + amount$ + " & rate=" + rate$ + " & term=" + term$
  63. '
  64. ' store the execution start time
  65. '
  66. timeStart# = TIMER(0.001)
  67. '
  68. ' check if the expected arguments names and argument values are the right ones and if so get their relevant values
  69. ' if one argument name or argument type isn't what is expected, use the default argument values.
  70. '
  71. WHILE NbArg% < 4
  72.     IF LEN(LineArg$) > 0 THEN
  73.         FOR i% = 1 TO LEN(LineArg$ + " ")
  74.             GetChar$ = MID$(LineArg$, i%, 1)
  75.             IF (GetChar$ <> "" AND GetChar$ <> " " AND GetChar$ <> "&") THEN
  76.                 Arg$ = Arg$ + GetChar$
  77.             ELSE
  78.                 IF Arg$ <> "" THEN
  79.                     SELECT CASE NbArg%
  80.                         CASE 0
  81.                             IF LEFT$(Arg$, 5) <> "name=" THEN
  82.                                 '    PRINT "problem with the " + CHR$(34) + "first argument naming that should be name= but is: " + CHR$(34) + LEFT$(Arg$, 5) + CHR$(34)
  83.                                 EXIT WHILE
  84.                             ELSEIF isValidArg%(MID$(Arg$, 6), "str") = 0 THEN
  85.                                 '    PRINT "problem with the content of name= that is: " + CHR$(34) + MID$(Arg$, 6) + CHR$(34) + " and isn't a valid string!"
  86.                                 EXIT WHILE
  87.                             ELSE
  88.                                 Arg$ = MID$(Arg$, 6)
  89.                             END IF
  90.                         CASE 1
  91.                             IF LEFT$(Arg$, 7) <> "amount=" THEN
  92.                                 '    PRINT "problem with the " + CHR$(34) + "second argument naming that should be amount= but is: " + CHR$(34) + LEFT$(Arg$, 7) + CHR$(34)
  93.                                 EXIT WHILE
  94.                             ELSEIF isValidArg%(MID$(Arg$, 8), "flt") = 0 THEN
  95.                                 '    PRINT "problem with the content of amount= that is: " + CHR$(34) + MID$(Arg$, 8) + CHR$(34) + " and isn't a valid float!"
  96.                                 EXIT WHILE
  97.                             ELSE
  98.                                 Arg$ = MID$(Arg$, 8)
  99.                             END IF
  100.                         CASE 2
  101.                             IF LEFT$(Arg$, 5) <> "rate=" THEN
  102.                                 '    PRINT "problem with the " + CHR$(34) + "third argument naming that should be rate= but is: " + CHR$(34) + LEFT$(Arg$, 5) + CHR$(34)
  103.                                 EXIT WHILE
  104.                             ELSEIF isValidArg%(MID$(Arg$, 6), "flt") = 0 THEN
  105.                                 '    PRINT "problem with the content of rate= that is: " + CHR$(34) + MID$(Arg$, 6) + CHR$(34) + " and isn't a valid float!"
  106.                                 EXIT WHILE
  107.                             ELSE
  108.                                 Arg$ = MID$(Arg$, 6)
  109.                             END IF
  110.                         CASE 3
  111.                             IF LEFT$(Arg$, 5) <> "term=" THEN
  112.                                 '    PRINT "problem with the " + CHR$(34) + "last argument naming that should be term= but is: " + CHR$(34) + LEFT$(Arg$, 5) + CHR$(34)
  113.                                 EXIT WHILE
  114.                             ELSEIF isValidArg%(MID$(Arg$, 6), "int") = 0 THEN
  115.                                 '    PRINT "problem with the content of rate= that is: " + CHR$(34) + MID$(Arg$, 6) + CHR$(34) + " and isn't a valid integer!"
  116.                                 EXIT WHILE
  117.                             ELSE
  118.                                 Arg$ = MID$(Arg$, 6)
  119.                             END IF
  120.                     END SELECT
  121.                     ArrayArg$(NbArg%) = Arg$
  122.                     Arg$ = ""
  123.                     NbArg% = NbArg% + 1
  124.                 END IF
  125.             END IF
  126.         NEXT i%
  127.     END IF
  128. '
  129. ' Default arguments
  130. '
  131. IF ArrayArg$(0) <> "" AND ArrayArg$(0) <> " " AND ArrayArg$(0) <> "-" THEN
  132.     name$ = ArrayArg$(0)
  133. ELSEIF yourname$ = "" THEN
  134.     name$ = "Client" ' default name
  135.     name$ = yourname$
  136. IF ArrayArg$(1) <> "" AND ArrayArg$(0) <> " " AND VAL(ArrayArg$(1)) > 1 THEN
  137.     Amount# = VAL(ArrayArg$(1))
  138. ELSEIF amount$ = "" THEN
  139.     Amount# = 10000.00 ' default amount
  140.     Amount# = VAL(amount$)
  141. IF ArrayArg$(2) <> "" AND ArrayArg$(2) <> " " AND VAL(ArrayArg$(2)) > 0 THEN
  142.     Rate# = VAL(ArrayArg$(2)) / 100
  143. ELSEIF rate$ = "" THEN
  144.     Rate# = 3.5 / 100 ' default rate
  145.     Rate# = VAL(rate$)
  146. IF Rate# > 20 THEN
  147.     Rate# = 20.00 ' default maximum rate
  148. IF ArrayArg$(3) <> "" AND ArrayArg$(3) <> " " AND VAL(ArrayArg$(3)) > 0 THEN
  149.     Term# = _ROUND(VAL(ArrayArg$(3)))
  150. ELSEIF term$ = "" THEN
  151.     Term# = 5 ' default term
  152.     Term# = VAL(term$)
  153. IF Term# > 99 THEN
  154.     Term# = 99 ' default maximum term
  155. '
  156. ' start the main routines of the program
  157. '
  158. '
  159. ' computation formulas of the monthly payment and global cost
  160. '
  161. Payment# = Amount# * Rate# / 12 * ((1 + Rate# / 12) ^ (Term# * 12)) / ((1 + Rate# / 12) ^ (Term# * 12) - 1)
  162. Cost# = (Term# * 12 * Payment#) - Amount#
  163. '
  164. ' prepare the first result$ string for output.
  165. '
  166. result$ = CHR$(13) + CHR$(10) + "Dear " + name$ + ", the requested loan goes as follows:" + CHR$(13) + CHR$(10)
  167. Ratio# = 100 / (Amount# / Cost#)
  168. '
  169. ' add the next statements
  170. '
  171. result$ = result$ + "Loan" + CHR$(9) + "details" + CHR$(13) + CHR$(10)
  172. result$ = result$ + "Amount" + CHR$(9) + printUsing$(Amount#) + CHR$(13) + CHR$(10)
  173. result$ = result$ + "Rate" + CHR$(9) + printUsing$(Rate# * 100) + "%" + CHR$(13) + CHR$(10)
  174. result$ = result$ + "Term" + CHR$(9) + LTRIM$(STR$(Term#)) + " year(s)" + CHR$(13) + CHR$(10)
  175. result$ = result$ + "Cost" + CHR$(9) + printUsing$(Cost#) + " (" + printUsing$(Ratio#) + "%)" + CHR$(13) + CHR$(10)
  176. '
  177. ' add the monthly computations
  178. '
  179. FOR i% = 1 TO Term#
  180.     '
  181.     ' add the next statements
  182.     '
  183.     result$ = result$ + CHR$(13) + CHR$(10) + "YEAR" + STR$(Year%) + CHR$(13) + CHR$(10)
  184.     result$ = result$ + "month" + CHR$(9) + CHR$(9) + "payment" + CHR$(9) + CHR$(9) + "interest" + CHR$(9) + "principal" + CHR$(9) + "balance" + CHR$(13) + CHR$(10)
  185.     '
  186.     ' Call the compute sub routine
  187.     '
  188.     CALL compute(Month%, Amount#, Rate#, Interest#, Payment#, Principal#, lastPayment#, result$)
  189.     IF Month% = 12 THEN
  190.         IF Amount# > 0 THEN
  191.             Month% = 0
  192.             Year% = Year% + 1
  193.         END IF
  194.     END IF
  195. NEXT i%
  196. '
  197. ' add the elapsed time to execute the program
  198. '
  199. timeEnd# = TIMER(0.001)
  200. '
  201. ' add the last statements
  202. '
  203. result$ = result$ + "This table was generated in " + printUsing$(((timeEnd# - timeStart#) * 1000)) + " ms. "
  204. result$ = result$ + "(on a 3GHz CPU 1 ms = 3,000,000 cycles)"
  205. '
  206. ' option: unrem to create the .txt files
  207. '
  208. 'CALL createFile("loan-calculator.txt", result$)
  209. '
  210. ' print the result into the console
  211. '
  212. PRINT result$
  213. '
  214. ' wait for an input
  215. '
  216. 'INPUT (a)
  217. '
  218. ' end of the program and exit from the console with a 200 return
  219. '
  220. 'SYSTEM 200
  221. '
  222. ' sub routine to create the loan-bas.html and loan-bas.txt files
  223. '
  224. SUB createFile (fileName$, result$)
  225. '
  226. ' delete the old fileName$ file
  227. '
  228. IF _FILEEXISTS(fileName$) THEN
  229.     KILL fileName$
  230. '
  231. ' create the fileName$ file
  232. '
  233. IF existFile%(fileName$) = 0 THEN
  234.     OPEN fileName$ FOR APPEND AS #1
  235.     PRINT #1, result$
  236.     CLOSE #1
  237. '
  238. ' sub routine to compute and print the monthly elements
  239. '
  240. SUB compute (Month%, Amount#, Rate#, Interest#, Payment#, Principal#, lastPayment#, result$)
  241.     SHARED Month%, _
  242.            Amount#, _
  243.            Rate#, _
  244.            Interest#, _
  245.            Payment#, _
  246.            Principal#, _
  247.            lastPayment#, _
  248.            formatNumber$, _
  249.            result$
  250. DIM monthList$(11)
  251. monthList$(0) = "January"
  252. monthList$(1) = "February"
  253. monthList$(2) = "March"
  254. monthList$(3) = "April"
  255. monthList$(4) = "May "
  256. monthList$(5) = "June"
  257. monthList$(6) = "July"
  258. monthList$(7) = "August"
  259. monthList$(8) = "September"
  260. monthList$(9) = "October"
  261. monthList$(10) = "November"
  262. monthList$(11) = "December"
  263. interest$ = "Interest: "
  264. payment$ = "Payment: "
  265. principal$ = "Principal: "
  266. FOR Month% = 0 TO 11
  267.     Interest# = (Amount# * Rate#) / 12
  268.     IF Amount# > Payment# THEN
  269.         Amount# = (Amount# - Payment#) + Interest#
  270.         Principal# = Payment# - Interest#
  271.     ELSE
  272.         IF lastPayment# > 0 THEN
  273.             lastPayment# = 0
  274.             Payment# = Amount#
  275.             Principal# = Amount# - Interest#
  276.             Amount# = 0
  277.         ELSE
  278.             Amount# = 0
  279.             Payment# = 0
  280.             Interest# = 0
  281.             Principal# = 0
  282.         END IF
  283.     END IF
  284.     '
  285.     ' add the next statements
  286.     '
  287.     IF monthList$(Month%) = "February" OR monthList$(Month%) = "September" OR monthList$(Month%) = "November" OR monthList$(Month%) = "December" THEN
  288.         result$ = result$ + monthList$(Month%) + CHR$(9)
  289.     ELSE
  290.         result$ = result$ + monthList$(Month%) + CHR$(9) + CHR$(9)
  291.     END IF
  292.     IF LEN(printUsing$(Payment#)) > 7 THEN
  293.         result$ = result$ + printUsing$(Payment#) + CHR$(9)
  294.     ELSE
  295.         result$ = result$ + printUsing$(Payment#) + CHR$(9) + CHR$(9)
  296.     END IF
  297.     IF LEN(printUsing$(Interest#)) > 7 THEN
  298.         result$ = result$ + printUsing$(Interest#) + CHR$(9)
  299.     ELSE
  300.         result$ = result$ + printUsing$(Interest#) + CHR$(9) + CHR$(9)
  301.     END IF
  302.     IF LEN(printUsing$(Principal#)) > 7 THEN
  303.         result$ = result$ + printUsing$(Principal#) + CHR$(9)
  304.     ELSE
  305.         result$ = result$ + printUsing$(Principal#) + CHR$(9) + CHR$(9)
  306.     END IF
  307.     result$ = result$ + printUsing$(Amount#) + CHR$(13) + CHR$(10)
  308. result$ = result$ + CHR$(13) + CHR$(10)
  309. '
  310. ' function to check if an argument is a valid string to be processed by this loan.bas program
  311. '
  312. FUNCTION isValidArg% (arg$, type$)
  313. isValidArg% = 0
  314. isStr% = 0
  315.     CASE "str"
  316.         t$ = LCASE$(arg$)
  317.         base$ = "abcdefghijklmnopqrstuvwxyz-"
  318.     CASE "flt"
  319.         base$ = ".1234567890"
  320.         IF LEN(arg$) = 1 AND arg$ = "." THEN
  321.             isValidArg% = 0
  322.             EXIT FUNCTION
  323.         END IF
  324.     CASE "int"
  325.         base$ = "1234567890"
  326.     CASE ELSE
  327.         arg$ = ""
  328.         type$ = ""
  329.         isValidArg% = 0
  330.         EXIT FUNCTION
  331. isValidArg% = 0
  332. isStr% = 0
  333. t$ = LCASE$(arg$)
  334. FOR i = 1 TO LEN(arg$)
  335.     argChar$ = MID$(t$, i, 1)
  336.     FOR j = 1 TO LEN(base$)
  337.         baseChar$ = MID$(base$, j, 1)
  338.         IF baseChar$ = argChar$ THEN
  339.             isValidArg% = isValidArg% + 1
  340.             isStr% = 1
  341.             EXIT FOR
  342.         ELSE
  343.             isStr% = 0
  344.             IF (j = LEN(base$)) THEN
  345.                 isStr% = 0
  346.                 EXIT FOR
  347.             END IF
  348.         END IF
  349.     NEXT j
  350.     IF isStr% = 0 THEN
  351.         isValidArg% = 0
  352.         EXIT FOR
  353.     END IF
  354. '
  355. '
  356. '
  357. FUNCTION existFile% (fileName$)
  358. OPEN fileName$ FOR APPEND AS #f%
  359. IF LOF(f%) THEN
  360.     existFile% = 1
  361.     CLOSE #f%
  362.     existFile% = 0
  363.     CLOSE #f%
  364.     KILL fileName$
  365. '
  366. ' function to format the integer part of a float and round its decimal part
  367. '
  368. FUNCTION printUsing$ (nb#)
  369. printUsing$ = intPart$(nb#) + decPart$(nb#)
  370. '
  371. ' function to format and round the decimal part of a float
  372. '
  373. FUNCTION decPart$ (nb#)
  374. dot$ = "."
  375. dotPos% = INSTR(LTRIM$(STR$(nb#)), dot$)
  376. IF dotPos% = 0 THEN
  377.     partdec$ = ".00"
  378.     partdec$ = MID$(LTRIM$(STR$(nb#)), dotPos%)
  379.     strlen% = LEN(partdec$)
  380. IF strlen% = 1 THEN
  381.     partdec$ = ".00"
  382.     SELECT CASE strlen%
  383.         CASE 2
  384.             partdec$ = partdec$ + "0"
  385.         CASE IS > 3
  386.             IF VAL(MID$(partdec$, 4, 1)) >= 5 THEN
  387.                 MID$(partdec$, 3, 1) = LTRIM$(STR$(VAL(MID$(partdec$, 3, 1)) + 1))
  388.             END IF
  389.             partdec$ = LEFT$(partdec$, 3)
  390.     END SELECT
  391. decPart$ = partdec$
  392. '
  393. ' function to format the integer part of a float
  394. '
  395. FUNCTION intPart$ (nb#)
  396. i$ = LTRIM$(RTRIM$(STR$(FIX(nb#))))
  397. IF nb# < 0 THEN
  398.     i$ = MID$(i$, 2)
  399. lenI = LEN(i$)
  400. IF lenI > 3 THEN
  401.     m3 = lenI MOD 3
  402.     IF m3 <> 0 THEN
  403.         i$ = LEFT$(i$, m3) + "," + MID$(i$, m3 + 1)
  404.     END IF
  405.     idx = m3 + 4 + (m3 = 0)
  406.     WHILE idx < LEN(i$)
  407.         i$ = LEFT$(i$, idx) + "," + MID$(i$, idx + 1)
  408.         idx = idx + 4
  409.     WEND
  410. ELSEIF lenI = 0 THEN
  411.     i$ = "0"
  412. IF nb# < 0 AND lenI > 0 THEN
  413.     i$ = "-" + i$
  414. intPart$ = i$
  415.  

Please tell me where I may be wrong (nobody's perfect).

Cheers.
Fifi
It's better to look like an idiot for a short time while asking something obvious to an expert than pretending to be smart all your life. (C) Me.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Problems compiling to executables on Linux
« Reply #4 on: September 10, 2018, 06:19:44 pm »
Have you tried setting the -no-pie switch and then compiling?  It seemed to work for the OP.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Fifi

  • Forum Regular
  • Posts: 181
    • View Profile
    • My small QB64 contribution
Re: Problems compiling to executables on Linux
« Reply #5 on: September 11, 2018, 01:04:56 pm »
Hi SMcNeill

Have you tried setting the -no-pie switch and then compiling?  It seemed to work for the OP.

No, I didn't do since I don't see in what file I should do that !

Any hint will be appreciated.

Cheers.
Fifi
It's better to look like an idiot for a short time while asking something obvious to an expert than pretending to be smart all your life. (C) Me.

Offline Fifi

  • Forum Regular
  • Posts: 181
    • View Profile
    • My small QB64 contribution
Re: Problems compiling to executables on Linux
« Reply #6 on: September 11, 2018, 06:57:56 pm »
Hi all,

I found an old VM I saved on a spare disk running Ubuntu Trusty 14.04.1 64-bit and QB64 v1,0

Unfortunately, the problem described above was already there.

To sum up, on Linux, QB64 can compile and fire tiny source files, the executables been able to be fired with a double left mouse click.

However, it can only compile even medium sized source file but is not be able to fire it from the IDE, the executable been then only able to be fired by the command line and not with the mouse action.

And the amazing thing is this problem occurs only with terminal programs (such as the loan sample I already gave) and not with GUI apps made with InForm.

So, as a matter of fact, this problem exists for a while and never ever was fixed since, I guess, there are very few QB64 coders on Linux.

Meanwhile, I'd like to test the -no-pie switch but I've no clue where and how to do so and I'd appreciate an explanation how to do this.

T.I.A.
Fifi

Below is a new version of this loan program that fits into a regular 80x25 terminal. T.I.A. to test it on your system (windows, Linux and OS/X) and please tell me how it works for you when fired from the IDE or with a left double click.

Code: QB64: [Select]
  1. '
  2. ' Program name: loan.bas
  3. '
  4. ' Program that computes for a client the montly payments, interest, principal
  5. ' and balance for a certain amount with a certain fixed interest rate and for
  6. ' a certain number of years and prints the amortization table.
  7. '
  8. ' The executable can be launched with four parameters : name of the client,
  9. ' amount, interest and term.
  10. '
  11. ' The parameters must be entered using a command line arguments in a string of
  12. ' the form: "&name=abcd&amount=xxx&rate=rr.rr&term=zz"
  13. ' where name is the client name (a string without space)
  14. ' xxx is the amount (a long)
  15. ' rr.rr is the rate (a float) - maximum 20
  16. ' and zz is the number of years (an int) - maximun 99
  17. ' e.g. loan &name=John&amount=12000&rate=2.57&term=5
  18. '
  19. ' NOTE:
  20. ' Space(s) can be included between arguments but not between the argument
  21. ' and the sign "=" nor between the sign "=" and the argument value such as:
  22. ' e.g. loan & name=John & amount=12000 & rate=2.57 & term=5
  23. '
  24. ' NOTE:
  25. ' Only the dot sign "." is allowed in float to separate the integer part from
  26. ' its decimal part (no comma sign "," anywhere in a float).
  27. '
  28. ' NOTE:
  29. ' If no parameters are set, the program ask you the values.
  30. ' If there is no value entered (just hit the Enter key), the program computes
  31. ' the default values (Client, 10000.00, 3.5% and 5 years).
  32. '
  33. '
  34. ' title of the windows when used in a console
  35. '
  36. _TITLE "Loan calculator"
  37. '
  38. ' miscelaneous variables initialisation
  39. '
  40. Arg$ = ""
  41. NbArg% = 0
  42. DIM ArrayArg$(4)
  43. lastPayment# = 1.00
  44. Year% = 1
  45. '
  46. ' Get the Arguments of the command line
  47. '
  48. LineArg$ = COMMAND$
  49. '
  50. ' force parameters if the argument line is empty.
  51. '
  52. IF LEN(LineArg$) = 0 THEN
  53.     '    LineArg$ = "& name=- & amount=10000.00 & rate=3.5 & term=1"
  54.     PRINT "Please enter your name (any name, may be empty but no space):     ";
  55.     INPUT yourname$
  56.     PRINT "Amount to borrow (long, decimal characters) e.g. 1000000:         ";
  57.     INPUT amount$
  58.     PRINT "Rate of the loan (float, decimal characters with .) e.g. 1.65 :   ";
  59.     INPUT rate$
  60.     PRINT "Number of year of the loan (integer, decimal characters) e.g. 12: ";
  61.     INPUT term$
  62.     LineArg$ = "& name=" + yourname$ + " & amount=" + amount$ + " & rate=" + rate$ + " & term=" + term$
  63. '
  64. ' store the execution start time
  65. '
  66. timeStart# = TIMER(0.001)
  67. '
  68. ' check if the expected arguments names and argument values are the right ones and if so get their relevant values
  69. ' if one argument name or argument type isn't what is expected, use the default argument values.
  70. '
  71. WHILE NbArg% < 4
  72.     IF LEN(LineArg$) > 0 THEN
  73.         FOR i% = 1 TO LEN(LineArg$ + " ")
  74.             GetChar$ = MID$(LineArg$, i%, 1)
  75.             IF (GetChar$ <> "" AND GetChar$ <> " " AND GetChar$ <> "&") THEN
  76.                 Arg$ = Arg$ + GetChar$
  77.             ELSE
  78.                 IF Arg$ <> "" THEN
  79.                     SELECT CASE NbArg%
  80.                         CASE 0
  81.                             IF LEFT$(Arg$, 5) <> "name=" THEN
  82.                                 '    PRINT "problem with the " + CHR$(34) + "first argument naming that should be name= but is: " + CHR$(34) + LEFT$(Arg$, 5) + CHR$(34)
  83.                                 EXIT WHILE
  84.                             ELSEIF isValidArg%(MID$(Arg$, 6), "str") = 0 THEN
  85.                                 '    PRINT "problem with the content of name= that is: " + CHR$(34) + MID$(Arg$, 6) + CHR$(34) + " and isn't a valid string!"
  86.                                 EXIT WHILE
  87.                             ELSE
  88.                                 Arg$ = MID$(Arg$, 6)
  89.                             END IF
  90.                         CASE 1
  91.                             IF LEFT$(Arg$, 7) <> "amount=" THEN
  92.                                 '    PRINT "problem with the " + CHR$(34) + "second argument naming that should be amount= but is: " + CHR$(34) + LEFT$(Arg$, 7) + CHR$(34)
  93.                                 EXIT WHILE
  94.                             ELSEIF isValidArg%(MID$(Arg$, 8), "flt") = 0 THEN
  95.                                 '    PRINT "problem with the content of amount= that is: " + CHR$(34) + MID$(Arg$, 8) + CHR$(34) + " and isn't a valid float!"
  96.                                 EXIT WHILE
  97.                             ELSE
  98.                                 Arg$ = MID$(Arg$, 8)
  99.                             END IF
  100.                         CASE 2
  101.                             IF LEFT$(Arg$, 5) <> "rate=" THEN
  102.                                 '    PRINT "problem with the " + CHR$(34) + "third argument naming that should be rate= but is: " + CHR$(34) + LEFT$(Arg$, 5) + CHR$(34)
  103.                                 EXIT WHILE
  104.                             ELSEIF isValidArg%(MID$(Arg$, 6), "flt") = 0 THEN
  105.                                 '    PRINT "problem with the content of rate= that is: " + CHR$(34) + MID$(Arg$, 6) + CHR$(34) + " and isn't a valid float!"
  106.                                 EXIT WHILE
  107.                             ELSE
  108.                                 Arg$ = MID$(Arg$, 6)
  109.                             END IF
  110.                         CASE 3
  111.                             IF LEFT$(Arg$, 5) <> "term=" THEN
  112.                                 '    PRINT "problem with the " + CHR$(34) + "last argument naming that should be term= but is: " + CHR$(34) + LEFT$(Arg$, 5) + CHR$(34)
  113.                                 EXIT WHILE
  114.                             ELSEIF isValidArg%(MID$(Arg$, 6), "int") = 0 THEN
  115.                                 '    PRINT "problem with the content of rate= that is: " + CHR$(34) + MID$(Arg$, 6) + CHR$(34) + " and isn't a valid integer!"
  116.                                 EXIT WHILE
  117.                             ELSE
  118.                                 Arg$ = MID$(Arg$, 6)
  119.                             END IF
  120.                     END SELECT
  121.                     ArrayArg$(NbArg%) = Arg$
  122.                     Arg$ = ""
  123.                     NbArg% = NbArg% + 1
  124.                 END IF
  125.             END IF
  126.         NEXT i%
  127.     END IF
  128. '
  129. ' Default arguments
  130. '
  131. IF ArrayArg$(0) <> "" AND ArrayArg$(0) <> " " AND ArrayArg$(0) <> "-" THEN
  132.     name$ = ArrayArg$(0)
  133. ELSEIF yourname$ = "" THEN
  134.     name$ = "Client" ' default name
  135.     name$ = yourname$
  136. IF ArrayArg$(1) <> "" AND ArrayArg$(0) <> " " AND VAL(ArrayArg$(1)) > 1 THEN
  137.     Amount# = VAL(ArrayArg$(1))
  138. ELSEIF amount$ = "" THEN
  139.     Amount# = 10000.00 ' default amount
  140.     Amount# = VAL(amount$)
  141. IF ArrayArg$(2) <> "" AND ArrayArg$(2) <> " " AND VAL(ArrayArg$(2)) > 0 THEN
  142.     Rate# = VAL(ArrayArg$(2)) / 100
  143. ELSEIF rate$ = "" THEN
  144.     Rate# = 3.5 / 100 ' default rate
  145.     Rate# = VAL(rate$)
  146. IF Rate# > 20 THEN
  147.     Rate# = 20.00 ' default maximum rate
  148. IF ArrayArg$(3) <> "" AND ArrayArg$(3) <> " " AND VAL(ArrayArg$(3)) > 0 THEN
  149.     Term# = _ROUND(VAL(ArrayArg$(3)))
  150. ELSEIF term$ = "" THEN
  151.     Term# = 5 ' default term
  152.     Term# = VAL(term$)
  153. IF Term# > 99 THEN
  154.     Term# = 99 ' default maximum term
  155. '
  156. ' start the main routines of the program
  157. '
  158. '
  159. ' computation formulas of the monthly payment and global cost
  160. '
  161. Payment# = Amount# * Rate# / 12 * ((1 + Rate# / 12) ^ (Term# * 12)) / ((1 + Rate# / 12) ^ (Term# * 12) - 1)
  162. Cost# = (Term# * 12 * Payment#) - Amount#
  163. '
  164. ' prepare the first result$ string for output.
  165. '
  166. result$ = CHR$(13) + CHR$(10) + "Dear " + name$ + ", the requested loan goes as follows:" + CHR$(13) + CHR$(10)
  167. Ratio# = 100 / (Amount# / Cost#)
  168. '
  169. ' add the next statements
  170. '
  171. result$ = result$ + "Loan" + CHR$(9) + "details" + CHR$(13) + CHR$(10)
  172. result$ = result$ + "Amount" + CHR$(9) + printUsing$(Amount#) + CHR$(13) + CHR$(10)
  173. result$ = result$ + "Rate" + CHR$(9) + printUsing$(Rate# * 100) + "%" + CHR$(13) + CHR$(10)
  174. result$ = result$ + "Term" + CHR$(9) + LTRIM$(STR$(Term#)) + " year(s)" + CHR$(13) + CHR$(10)
  175. result$ = result$ + "Cost" + CHR$(9) + printUsing$(Cost#) + " (" + printUsing$(Ratio#) + "%)" + CHR$(13) + CHR$(10)
  176. '
  177. ' add the monthly computations
  178. '
  179. FOR i% = 1 TO Term#
  180.     '
  181.     ' add the next statements
  182.     '
  183.     result$ = result$ + CHR$(13) + CHR$(10) + "YEAR" + STR$(Year%) + CHR$(13) + CHR$(10)
  184.     result$ = result$ + "month" + CHR$(9) + CHR$(9) + "payment" + CHR$(9) + CHR$(9) + "interest" + CHR$(9) + "principal" + CHR$(9) + "balance" + CHR$(13) + CHR$(10)
  185.     '
  186.     ' Call the compute sub routine
  187.     '
  188.     CALL compute(Month%, Amount#, Rate#, Interest#, Payment#, Principal#, lastPayment#, result$)
  189.     IF Month% = 12 THEN
  190.         IF Amount# > 0 THEN
  191.             Month% = 0
  192.             Year% = Year% + 1
  193.         END IF
  194.     END IF
  195. NEXT i%
  196. '
  197. ' add the elapsed time to execute the program
  198. '
  199. timeEnd# = TIMER(0.001)
  200. '
  201. ' add the last statements
  202. '
  203. result$ = result$ + "This table was generated in " + printUsing$(((timeEnd# - timeStart#) * 1000)) + " ms. "
  204. result$ = result$ + "(on a 3GHz CPU 1 ms = 3,000,000 cycles)"
  205. '
  206. ' option: unrem to create the .txt files
  207. '
  208. 'CALL createFile("loan-calculator.txt", result$)
  209. '
  210. ' print the result into the console
  211. '
  212. PRINT result$
  213. '
  214. ' wait for an input
  215. '
  216. 'INPUT (a)
  217. '
  218. ' end of the program and exit from the console with a 200 return
  219. '
  220. 'SYSTEM 200
  221. '
  222. ' sub routine to create the loan-bas.html and loan-bas.txt files
  223. '
  224. SUB createFile (fileName$, result$)
  225. '
  226. ' delete the old fileName$ file
  227. '
  228. IF _FILEEXISTS(fileName$) THEN
  229.     KILL fileName$
  230. '
  231. ' create the fileName$ file
  232. '
  233. IF existFile%(fileName$) = 0 THEN
  234.     OPEN fileName$ FOR APPEND AS #1
  235.     PRINT #1, result$
  236.     CLOSE #1
  237. '
  238. ' sub routine to compute and print the monthly elements
  239. '
  240. SUB compute (Month%, Amount#, Rate#, Interest#, Payment#, Principal#, lastPayment#, result$)
  241.     SHARED Month%, _
  242.            Amount#, _
  243.            Rate#, _
  244.            Interest#, _
  245.            Payment#, _
  246.            Principal#, _
  247.            lastPayment#, _
  248.            formatNumber$, _
  249.            result$
  250. DIM monthList$(11)
  251. monthList$(0) = "January"
  252. monthList$(1) = "February"
  253. monthList$(2) = "March"
  254. monthList$(3) = "April"
  255. monthList$(4) = "May "
  256. monthList$(5) = "June"
  257. monthList$(6) = "July"
  258. monthList$(7) = "August"
  259. monthList$(8) = "September"
  260. monthList$(9) = "October"
  261. monthList$(10) = "November"
  262. monthList$(11) = "December"
  263. interest$ = "Interest: "
  264. payment$ = "Payment: "
  265. principal$ = "Principal: "
  266. FOR Month% = 0 TO 11
  267.     Interest# = (Amount# * Rate#) / 12
  268.     IF Amount# > Payment# THEN
  269.         Amount# = (Amount# - Payment#) + Interest#
  270.         Principal# = Payment# - Interest#
  271.     ELSE
  272.         IF lastPayment# > 0 THEN
  273.             lastPayment# = 0
  274.             Payment# = Amount#
  275.             Principal# = Amount# - Interest#
  276.             Amount# = 0
  277.         ELSE
  278.             Amount# = 0
  279.             Payment# = 0
  280.             Interest# = 0
  281.             Principal# = 0
  282.         END IF
  283.     END IF
  284.     '
  285.     ' add the next statements
  286.     '
  287.     IF monthList$(Month%) = "February" OR monthList$(Month%) = "September" OR monthList$(Month%) = "November" OR monthList$(Month%) = "December" THEN
  288.         result$ = result$ + monthList$(Month%) + CHR$(9)
  289.     ELSE
  290.         result$ = result$ + monthList$(Month%) + CHR$(9) + CHR$(9)
  291.     END IF
  292.     IF LEN(printUsing$(Payment#)) > 7 THEN
  293.         result$ = result$ + printUsing$(Payment#) + CHR$(9)
  294.     ELSE
  295.         result$ = result$ + printUsing$(Payment#) + CHR$(9) + CHR$(9)
  296.     END IF
  297.     IF LEN(printUsing$(Interest#)) > 7 THEN
  298.         result$ = result$ + printUsing$(Interest#) + CHR$(9)
  299.     ELSE
  300.         result$ = result$ + printUsing$(Interest#) + CHR$(9) + CHR$(9)
  301.     END IF
  302.     IF LEN(printUsing$(Principal#)) > 7 THEN
  303.         result$ = result$ + printUsing$(Principal#) + CHR$(9)
  304.     ELSE
  305.         result$ = result$ + printUsing$(Principal#) + CHR$(9) + CHR$(9)
  306.     END IF
  307.     result$ = result$ + printUsing$(Amount#) + CHR$(13) + CHR$(10)
  308. result$ = result$ + CHR$(13) + CHR$(10)
  309. '
  310. ' function to check if an argument is a valid string to be processed by this loan.bas program
  311. '
  312. FUNCTION isValidArg% (arg$, type$)
  313. isValidArg% = 0
  314. isStr% = 0
  315.     CASE "str"
  316.         t$ = LCASE$(arg$)
  317.         base$ = "abcdefghijklmnopqrstuvwxyz-"
  318.     CASE "flt"
  319.         base$ = ".1234567890"
  320.         IF LEN(arg$) = 1 AND arg$ = "." THEN
  321.             isValidArg% = 0
  322.             EXIT FUNCTION
  323.         END IF
  324.     CASE "int"
  325.         base$ = "1234567890"
  326.     CASE ELSE
  327.         arg$ = ""
  328.         type$ = ""
  329.         isValidArg% = 0
  330.         EXIT FUNCTION
  331. isValidArg% = 0
  332. isStr% = 0
  333. t$ = LCASE$(arg$)
  334. FOR i = 1 TO LEN(arg$)
  335.     argChar$ = MID$(t$, i, 1)
  336.     FOR j = 1 TO LEN(base$)
  337.         baseChar$ = MID$(base$, j, 1)
  338.         IF baseChar$ = argChar$ THEN
  339.             isValidArg% = isValidArg% + 1
  340.             isStr% = 1
  341.             EXIT FOR
  342.         ELSE
  343.             isStr% = 0
  344.             IF (j = LEN(base$)) THEN
  345.                 isStr% = 0
  346.                 EXIT FOR
  347.             END IF
  348.         END IF
  349.     NEXT j
  350.     IF isStr% = 0 THEN
  351.         isValidArg% = 0
  352.         EXIT FOR
  353.     END IF
  354. '
  355. '
  356. '
  357. FUNCTION existFile% (fileName$)
  358. OPEN fileName$ FOR APPEND AS #f%
  359. IF LOF(f%) THEN
  360.     existFile% = 1
  361.     CLOSE #f%
  362.     existFile% = 0
  363.     CLOSE #f%
  364.     KILL fileName$
  365. '
  366. ' function to format the integer part of a float and round its decimal part
  367. '
  368. FUNCTION printUsing$ (nb#)
  369. printUsing$ = intPart$(nb#) + decPart$(nb#)
  370. '
  371. ' function to format and round the decimal part of a float
  372. '
  373. FUNCTION decPart$ (nb#)
  374. dot$ = "."
  375. dotPos% = INSTR(LTRIM$(STR$(nb#)), dot$)
  376. IF dotPos% = 0 THEN
  377.     partdec$ = ".00"
  378.     partdec$ = MID$(LTRIM$(STR$(nb#)), dotPos%)
  379.     strlen% = LEN(partdec$)
  380. IF strlen% = 1 THEN
  381.     partdec$ = ".00"
  382.     SELECT CASE strlen%
  383.         CASE 2
  384.             partdec$ = partdec$ + "0"
  385.         CASE IS > 3
  386.             IF VAL(MID$(partdec$, 4, 1)) >= 5 THEN
  387.                 MID$(partdec$, 3, 1) = LTRIM$(STR$(VAL(MID$(partdec$, 3, 1)) + 1))
  388.             END IF
  389.             partdec$ = LEFT$(partdec$, 3)
  390.     END SELECT
  391. decPart$ = partdec$
  392. '
  393. ' function to format the integer part of a float
  394. '
  395. FUNCTION intPart$ (nb#)
  396. i$ = LTRIM$(RTRIM$(STR$(FIX(nb#))))
  397. IF nb# < 0 THEN
  398.     i$ = MID$(i$, 2)
  399. lenI = LEN(i$)
  400. IF lenI > 3 THEN
  401.     m3 = lenI MOD 3
  402.     IF m3 <> 0 THEN
  403.         i$ = LEFT$(i$, m3) + "," + MID$(i$, m3 + 1)
  404.     END IF
  405.     idx = m3 + 4 + (m3 = 0)
  406.     WHILE idx < LEN(i$)
  407.         i$ = LEFT$(i$, idx) + "," + MID$(i$, idx + 1)
  408.         idx = idx + 4
  409.     WEND
  410. ELSEIF lenI = 0 THEN
  411.     i$ = "0"
  412. IF nb# < 0 AND lenI > 0 THEN
  413.     i$ = "-" + i$
  414. intPart$ = i$
  415.  
It's better to look like an idiot for a short time while asking something obvious to an expert than pretending to be smart all your life. (C) Me.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Problems compiling to executables on Linux
« Reply #7 on: September 11, 2018, 07:25:34 pm »
Internal/c/makeline_lnx.txt holds the compiler switches for Linux.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Fifi

  • Forum Regular
  • Posts: 181
    • View Profile
    • My small QB64 contribution
Re: Problems compiling to executables on Linux
« Reply #8 on: September 12, 2018, 11:33:09 pm »
Hi SMcNeil,

Internal/c/makeline_lnx.txt holds the compiler switches for Linux.

Thanx for this tip.

So, I did the modification, and it's better since executable can now be fired with a double left click, but still not for program in a console.

Further, when doing so and recompiling QB64 with this option within it's source location makes QB64 not launchable (error message saying : cannot locate the 'internal' folder.)

So as said by dchr, now the executable isn't anymore position independant.

So, there are two real problems :

1) even medium programs such as my loan.bas using the console can't be fired from the IDE, and that's a very old problem for vWATCH64 (hello fellippe).

2) the option "Output executable in the source folder" doesn't work anymore since the created executable can't be fired at all.

Hope this helps.

Cheers.
Fifi
It's better to look like an idiot for a short time while asking something obvious to an expert than pretending to be smart all your life. (C) Me.